package cn.murky.tenant.system.biz.mq;

import cn.murky.common.domain.dto.SchemaInitDTO;
import cn.murky.core.exception.ServiceException;
import cn.murky.redismq.RedisMqTemplate;
import cn.murky.tenant.core.SecurityTenantUserInfo;
import cn.murky.tenant.core.utils.SecurityUtils;
import cn.murky.tenant.system.biz.domian.entity.SysDept;
import cn.murky.tenant.system.biz.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.noear.redisx.RedisClient;
import org.noear.snack.ONode;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.TranAnno;
import org.noear.solon.data.tran.TranUtils;

import static cn.murky.redismq.constant.SysTopicConstant.TENANT_INIT_TOPIC;
import static cn.murky.tenant.system.api.constant.ErrorConstant.INIT_TENANT_DATA_ERROR;

/**
 * 用来处理租户模式创建后的初始化数据事件
 */
@Slf4j
@Component
public class SchemaInitMqTemplate implements RedisMqTemplate {
    @Inject
    private RedisClient redisClient;
    @Inject
    private ISysDeptService iSysDeptService;
    @Inject("${murky.tenant.schemaPrefix}")
    private String tenantSchemaPrefix;
    @Inject("${murky.admin.schema}")
    private String adminSchemaName;

    @Override
    public boolean subscribe() {
        log.info("[SchemaInitMqTemplate] -> 订阅主题 -> topic:{}", getTopic());
        redisClient.getBus().subscribe((topic, msg) -> {
            // 分布式锁,在集群环境下防止重复刷新缓存
            SchemaInitDTO schemaInitDTO = ONode.deserialize(msg, SchemaInitDTO.class);
            if (redisClient.getLock(STR."\{getTopic()}:LOCK:\{schemaInitDTO.getId()}").tryLock(5)) {
                log.info("[SchemaInitMqTemplate] -> 消费消息 -> topic:{},msg:{}", topic, msg);
                try {
                    TranUtils.execute(new TranAnno(), ()->{
                        initSchema(schemaInitDTO);
                    });
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }

            }
        }, getTopic());
        return true;
    }

    private void initSchema(SchemaInitDTO schemaInitDTO){
        SecurityTenantUserInfo securityTenantUserInfo = new SecurityTenantUserInfo().setTenantId(schemaInitDTO.getId());
        SecurityUtils.runnable(securityTenantUserInfo,()->{
            boolean save = new SysDept()
                    .setDeptName(schemaInitDTO.getTenantName())
                    .setSort(0)
                    .setParentId(0L).save();
            if (!save) {
                throw new ServiceException(INIT_TENANT_DATA_ERROR);
            }
        });
    }

    @Override
    public String getTopic() {
        return TENANT_INIT_TOPIC;
    }
}
